﻿using System;
using System.Configuration;
using System.DirectoryServices.Protocols;
using System.Linq;
using System.Net;
using System.Security.Principal;
using System.Text;
using System.Web.Security;
using System.Web.UI.WebControls;
using ASBCC.Business;
using ASBCC.Database.EntityFramework;


namespace BEGDC.CC.Web
{
    /// <summary>
    /// Summary description for login.
    /// </summary>
    public class login : System.Web.UI.Page
    {
        private void Page_Load(object sender, System.EventArgs e)
        {
        }


        protected void Login_Authenticate(object sender, AuthenticateEventArgs e)
        {
            var server = ConfigurationManager.AppSettings["LDAP_Path"];
            var offlineMode = bool.Parse(ConfigurationManager.AppSettings["IsOffline"]);


            var login = sender as Login;
            Employee currentEmployee = null;
            e.Authenticated = offlineMode ?
                SQLAuthenticate(login.UserName, out currentEmployee) :
                CILAuthenticate(server, login.UserName, login.Password) && SQLAuthenticate(login.UserName, out currentEmployee);

            //if Authenticate success , inject the cookies contains username and role2s in client
            if (e.Authenticated)
            {
                StringBuilder sb = new StringBuilder();
                sb.AppendFormat("{0};", currentEmployee.NameEN);
                foreach (var r in currentEmployee.Roles)
                {
                    sb.AppendFormat("{0};", r.RoleID);
                }
                FormsAuthenticationTicket ticket = new FormsAuthenticationTicket(1, currentEmployee.NameEN, DateTime.Now, DateTime.Now.AddHours(1.0), false, sb.ToString());
                string cookieStr = FormsAuthentication.Encrypt(ticket);
                this.Response.Cookies["useroles"].Value = cookieStr;
                this.Response.Cookies["useroles"].Path = "/";
                //this.Response.Cookies["useroles"].Expires = DateTime.Now.AddMinutes(1.0);
                GlobalHelper.LogOperation(currentEmployee.NameEN, SystemModule.Admin, "User: " + currentEmployee.NameEN + "; Log in (登陆): " + DateTime.Now);
            }
            else
            {
                ClientScript.RegisterClientScriptBlock(GetType(), "login", "<script>alert('" + Resources.Messages.LoginFailed + "');</script>");
            }
        }

        private static bool SQLAuthenticate(string username, out Employee theEmployee)
        {
            using (var dc = new CCEntities())
            {
                theEmployee = dc.Employees.FirstOrDefault(p => p.NameEN == username && p.IsActived == true && p.IsEnabled == true);
                if (theEmployee == null) return false;
                theEmployee.Roles.Load();
                return true;
            }
        }

        // Exceptions:
        //   System.ObjectDisposedException:
        //   System.DirectoryServices.Protocols.LdapException:
        //   System.InvalidOperationException:
        private static bool CILAuthenticate(string server, string username, string password)
        {
            LdapDirectoryIdentifier ldapID = new LdapDirectoryIdentifier(server);
            NetworkCredential credential = new NetworkCredential(username, password);
            using (LdapConnection ldapCn = new LdapConnection(ldapID, credential, AuthType.Basic))
            {
                try
                {
                    ldapCn.Bind();
                }
                catch (LdapException e)
                {
                    // if error code equals to 49, it means the network credential is invalid.
                    if (e.ErrorCode == 49)
                        return false;
                    else
                        throw;
                }
            }

            return true;
        }
    }
}
